<?php
require_once (dirname(__FILE__) . "/../../../config.php");
require_once (dirname(__FILE__) . "/DatabaseObject.php");
?>
<?php

// methods
/*
// constructor
public function __construct( $utable, $dtable, $dbconfig, $uid)

// uid management
//   The class has build-in permission management.
//   If uid is specified in __construct() or by setuid(),
//   the access would be limited only in the data that belong to the user.
public function setuid($id)

// add
public function add_users($tblinfo)
public function add_userdata( $tblinfo, $uid = null)

// delete
public function del_users( $uid )
public function del_userdata_byid($id)
public function del_userdata( $pid, $wid)

// update
public function update_users( $tblinfo, $uid = null)
public function update_userdata( $tblinfo, $wid, $uid = null)

// get
public function get_users($uid = null)
public function get_users_byemail($email)
public function get_userdata($cond, $uid = null)
public function get_udata($uid = null)

// misc
public function is_user_exist($email)
public function get_last_users_id()
public function get_last_userdata_id( $uid = null)

// error handling
public function isFailed()
public function getErrMessage()
public function getErrCode()
*/
?>
<?php

/*
 * WidgetFramework DB
 * Created: 200904 (TT Tsai)
 *
 * WidgetFramework database access object
 */
class WFGenericDao
{
    // main database object
    private $dbobj;
    private $users_table;
    private $userdata_table;
    // error handling
    private $errMessage = "";
    private $errCode = 0;
    // userid
    // - build-in permission control (build-in support)
    // - if userid was not specified (user == 0), the function would be ignored.
    private $userid = 0;
    // return valid uid
    private function valid_uid($uid){
        if($this->userid == 0){ // Not normal user
            if($uid != null){
                return $uid;
            }else{
                $this->errMessage = "uid is not specified";
                $this->errCode = 1;
                return null;
            }
        }else{ // normal user (can only query its uid)
            return $this->userid; // ignore parameter $uid (normal user)
        }
    }
    // is table name valid?
    private function valid_table($table){
        if($table != $this->users_table || $table != $this->userdata_table){
            $this->errMessage = "Invalid table";
            $this->errCode = 1;
            return false;
        }
        return true;
    }
    // private methods
    private function runSQL($sqlstring, $sqlvalues, $estring, $ecode){
        $query_result = $this->dbobj->query($sqlstring, $sqlvalues);
        // check error
        if($this->dbobj->isFailed()){
            $this->errMessage = $estring . ": " . $this->dbobj->getErrMessage();
            $this->errCode = $ecode;
            return FALSE;
        }
        return $query_result;
    }
    // Constructor
    public function __construct($utable, $dtable, $dbconfig, $uid){
        $this->users_table = $utable;
        $this->userdata_table = $dtable;
        $this->userid = $uid;
        $this->dbobj = new WFDatabaseObject($dbconfig);
        // check error
        if($this->dbobj->isFailed()){
            $this->errMessage = "Database initialization failed: " . $this->dbobj->getErrMessage();
            $this->errCode = 1;
        }
        return;
    }
    // set user id
    public function setuid($id){
        $this->userid = $id;
    }
    // add
    public function add_users($tblinfo){
        if(isset($tblinfo["email"]) && isset($tblinfo["pass"]) && isset($tblinfo["data"]) && isset($tblinfo["cdata"]) && isset($tblinfo["udata"]) && isset($tblinfo["pdata"]) && isset($tblinfo["lang"]) && isset($tblinfo["theme"])){
            $sqlstring = 'INSERT into ' . $this->users_table . ' (email, pass, data, cdata, udata, pdata, lang, theme) VALUES ( :email, :pass, :data, :cdata, :udata, :pdata, :lang, :theme)';
            $sqlvalues[':email'] = $tblinfo["email"];
            $sqlvalues[':pass'] = $tblinfo["pass"];
            $sqlvalues[':data'] = $tblinfo["data"];
            $sqlvalues[':cdata'] = $tblinfo["cdata"];
            $sqlvalues[':udata'] = $tblinfo["udata"];
            $sqlvalues[':pdata'] = $tblinfo["pdata"];
            $sqlvalues[':lang'] = $tblinfo["lang"];
            $sqlvalues[':theme'] = $tblinfo["theme"];
            return $this->runSQL($sqlstring, $sqlvalues, "Adding [" . $this->users_table . "] failed", 1);
        }else{
            $this->errMessage = "Insufficient data [" . $this->users_table . "]";
            $this->errCode = 1;
            return;
        }
    }
    public function set_default_widgetdata($email, $udata){
        // get uid
        $uinfolist = $this->get_users_byemail($email);
        $newuserid = $uinfolist[0]['id'];
        // add userdata
        $userdatalist = json_decode($udata, true);
        if(isset($userdatalist)){
            foreach($userdatalist as $wdata){
                $winfo['wid'] = $wdata['wid'];
                $winfo['modname'] = $wdata['modname'];
                // data is an object (we treat "data" as an object)
                $dataobj = array();
                $dataobj[] = $this->get_widgetdata_from_config($wdata['wid']);
                $winfo['data'] = json_encode($dataobj);
                $winfo['pid'] = $wdata['page'];
                $this->add_userdata($winfo, $newuserid);
                if($this->isFailed()){
                    $this->errMessage = "(adding user) " . $this->getErrMessage();
                    mydebug_log("[set_default_widgetdata] create_user() added userdata failed " . $this->getErrMessage());
                    return false;
                }
            }
        }
    }
    public function get_widgetdata_from_config($wid){
        global $wfconf_default_userdata;
        if(! $wfconf_default_userdata)
            return '';
        else{
            $found = false;
            $founddata = NULL;
            $userdatalist = json_decode($wfconf_default_userdata, true);
            foreach($userdatalist as $data){
                if($data['wid'] == $wid){
                    $found = true;
                    $founddata = $data['data'];
                    break;
                }
            }
            if($found)
                return $founddata;
            else
                return '';
        }
    }
    protected function getUserdataData($strUserdataData){
        $data = $strUserdataData;
        // if $data not yet addslashes
        myerror_log($data);
        if($data && false === strpos($data,'\"')){
            // Step1: 
            // ["{"title":"PS(Test)","scope":"#all","fushionview":1,"currentSort":5,"currentSortType":"DESC","acceptlevel":1,"sorting":"DeployedCount","product_type":"15.4"}"]
            // convert to
            // [\"{\"title\":\"PS(Test)\",\"scope\":\"#all\",\"fushionview\":1,\"currentSort\":5,\"currentSortType\":\"DESC\",\"acceptlevel\":1,\"sorting\":\"DeployedCount\",\"product_type\":\"15.4\"}\"]
            $data = addslashes($data);
            // Step2:
            // [\" replace to ["
            // \"] replace to "]
            $data = str_replace('[\"', '["', $data);
            $data = str_replace('\"]', '"]', $data);
        }
        return $data;
    }
    public function add_userdata($tblinfo, $uid = null){
        // specify uid
        $work_uid = $this->valid_uid($uid);
        if($work_uid == null){
            return;
        }
        if(isset($tblinfo["wid"]) && isset($tblinfo["modname"]) && isset($tblinfo["data"]) && isset($tblinfo["pid"])){
            $sqlstring = 'INSERT into ' . $this->userdata_table . ' (uid, wid, modname, data, pid,widget_key,param) VALUES (:uid, :wid, :modname, :data, :pid, :widget_key, :param)';
            $sqlvalues[':uid'] = $work_uid;
            $sqlvalues[':wid'] = $tblinfo["wid"];
            $sqlvalues[':modname'] = $tblinfo["modname"];
            
            $data = $this->getUserdataData($tblinfo["data"]);
            $sqlvalues[':data'] = $data;
            $sqlvalues[':pid'] = $tblinfo["pid"];
            $sqlvalues[':widget_key'] = $tblinfo["widget_key"];
            $sqlvalues[':param'] = $tblinfo["param"];
            return $this->runSQL($sqlstring, $sqlvalues, "Adding [" . $this->userdata_table . "] failed", 1);
        }else{
            $this->errMessage = "Insufficient data [" . $this->userdata_table . "]";
            $this->errCode = 1;
            return;
        }
    }
    // del
    public function del_users($uid){
        // if userid is 0, it can delete any record. (skip permission checking)
        if($this->userid != 0 && $this->userid != $uid){
            $this->errMessage = "Permission denied";
            $this->errCode = 1;
            return;
        }
        $sqlstring = 'DELETE from ' . $this->users_table . ' WHERE id=:uid';
        $sqlvalues[':uid'] = $uid;
        return $this->runSQL($sqlstring, $sqlvalues, "Deleting users failed", 1);
    }
    public function del_userdata_byid($id){
        // permission check
        if($this->userid != 0){
            $sqlstring = 'SELECT uid from ' . $this->userdata_table . ' WHERE id = :rid';
            $sqlvalues[':rid'] = $id;
            $query_result = $this->dbobj->query($sqlstring, $sqlvalues);
            if($this->dbobj->isFailed()){
                $this->errMessage = "Permission denied";
                $this->errCode = 1;
                return;
            }
            if($this->userid != $query_result[0]["uid"]){
                $this->errMessage = "Permission denied";
                $this->errCode = 1;
                return;
            }
        }
        // delete the record
        $sqlstring = 'DELETE from ' . $this->userdata_table . ' WHERE id=:rid';
        $sqlvalues[':rid'] = $id;
        return $this->runSQL($sqlstring, $sqlvalues, "Deleting userdata failed", 1);
    }
    public function del_userdata_byuid($uid){
        // if userid is 0, it can delete any record. (skip permission checking)
        if($this->userid != 0 && $this->userid != $uid){
            $this->errMessage = "Permission denied";
            $this->errCode = 1;
            return;
        }
        // delete the record
        $sqlstring = 'DELETE from ' . $this->userdata_table . ' WHERE uid=:rid';
        $sqlvalues[':rid'] = $uid;
        return $this->runSQL($sqlstring, $sqlvalues, "Deleting userdata failed", 1);
    }
    public function del_userdata($pid, $wid){
        // if pid or wid is 0, which means 'all'.
        $sqlstring = 'DELETE from ' . $this->userdata_table . ' WHERE ';
        $needAND = false;
        if($this->userid != 0){
            $sqlstring .= 'uid = :uid';
            $sqlvalues[':uid'] = $this->userid;
            $needAND = true;
        }
        if($pid != 0){
            if($needAND){
                $sqlstring .= ' AND pid = :pid';
                $sqlvalues[':pid'] = $pid;
            }else{
                $sqlstring .= ' pid = :pid';
                $needAND = true;
            }
            $sqlvalues[':pid'] = $pid;
        }
        if($wid != 0){
            if($needAND){
                $sqlstring .= ' AND wid = :wid';
            }else{
                $sqlstring .= ' wid = :wid';
            }
            $sqlvalues[':wid'] = $wid;
        }
        return $this->runSQL($sqlstring, $sqlvalues, "Deleting users failed", 1);
    }
    // update
    public function update_users($tblinfo, $uid = null){
        // specify uid
        $work_uid = $this->valid_uid($uid);
        if($work_uid == null){
            return;
        }
        $needComma = false;
        $sqlstring = 'UPDATE ' . $this->users_table . ' SET ';
        foreach($tblinfo as $k => $v){
            $key = ":" . $k;
            if($needComma){
                $sqlstring .= ', ' . $k . '=' . $key;
            }else{
                $sqlstring .= $k . '=' . $key;
                $needComma = true;
            }
            $sqlvalues[$key] = $v;
        }
        if($needComma == false){
            // no entry
            $this->errMessage = "nothing to update";
            $this->errCode = 1;
            return;
        }
        $sqlstring .= ' WHERE id=:uid';
        $sqlvalues[':uid'] = $work_uid;
        return $this->runSQL($sqlstring, $sqlvalues, "Updating users failed", 1);
    }
    public function update_userdata($tblinfo, $wid, $uid = null){
        // specify uid
        $work_uid = $this->valid_uid($uid);
        if($work_uid == null){
            return;
        }
        // get record id according to wid and uid
        $sqlstring = 'SELECT id from ' . $this->userdata_table . ' WHERE uid = :uid AND wid = :wid';
        $sqlvalues[':uid'] = $work_uid;
        $sqlvalues[':wid'] = $wid;
        $query_result = $this->dbobj->query($sqlstring, $sqlvalues);
        if($this->dbobj->isFailed()){
            $this->errMessage = "Permission denied";
            $this->errCode = 1;
            return;
        }
        if(! isset($query_result[0]) || (! isset($query_result[0]["id"]))){
            /*
             * TT.20090626: add auto-recovery function
             * If user want to update a non-existing userdata, it should create the record automatically.
             */
            // 1.check does record exist? (but not yours)
            $sqlstring = 'SELECT id from ' . $this->userdata_table . ' WHERE wid = :wid';
            $sqlvalues = array();
            $sqlvalues[':wid'] = $wid;
            $query_result = $this->dbobj->query($sqlstring, $sqlvalues);
            if(! isset($query_result[0])){
                // ok, record NOT found.
                // 2.now get module name from users.
                $uinfolist = $this->get_users();
                // does user exist?
                if((! $this->isFailed()) && isset($uinfolist[0])){
                    // ok, we get user info now.
                    // 3.find the record
                    $my_udata = json_decode($uinfolist[0]['udata'], true);
                    foreach($my_udata as $wmodule){
                        if($wmodule['wid'] == $wid){
                            // got!
                            // 4.insert a record
                            $winfo = array();
                            $winfo['wid'] = $wid;
                            $winfo['modname'] = $wmodule['modname'];
                            $winfo['data'] = $tblinfo['data'];
                            $winfo['pid'] = $tblinfo["pid"];
                            return $this->add_userdata($winfo);
                        }
                    }
                }
            }
            $this->errMessage = "record not found";
            $this->errCode = 1;
            return;
        }
        // get record id
        $rid = $query_result[0]["id"];
        $needComma = false;
        $sqlvalues = array();
        $sqlstring = 'UPDATE ' . $this->userdata_table . ' SET ';
        foreach($tblinfo as $k => $v){
            $key = ":" . $k;
            if($needComma){
                $sqlstring .= ', ' . $k . '=' . $key;
            }else{
                $sqlstring .= $k . '=' . $key;
                $needComma = true;
            }
            $sqlvalues[$key] = $v;
        }
        if($needComma == false){
            // no entry
            $this->errMessage = "nothing for update";
            $this->errCode = 1;
            return;
        }
        $sqlstring .= ' WHERE id=:rid';
        $sqlvalues[':rid'] = $rid;
        return $this->runSQL($sqlstring, $sqlvalues, "Updating " . $this->userdata_table . " failed", 1);
    }
    // get
    public function get_users($uid = null){ // $cond is condition array
        // specify uid
        $work_uid = $this->valid_uid($uid);
        if($work_uid == null){
            return;
        }
        // query string
        $sqlstring = 'SELECT * from ' . $this->users_table . ' WHERE id = :uid';
        $sqlvalues[':uid'] = $work_uid;
        return $this->runSQL($sqlstring, $sqlvalues, "Get " . $this->users_table . " failed", 1);
    }
    public function get_users_byemail($email){
        if($email == NULL){
            $this->errMessage = "empty email";
            $this->errCode = 1;
            return;
        }
        $sqlstring = 'SELECT * from ' . $this->users_table . ' WHERE email = :email';
        $sqlvalues[':email'] = $email;
        return $this->runSQL($sqlstring, $sqlvalues, "Get " . $this->users_table . " failed", 1);
    }
    public function get_userdata($cond, $uid = null){
        // specify uid
        $work_uid = $this->valid_uid($uid);
        if($work_uid == null){
            return;
        }
        // query string
        $sqlstring = 'SELECT * from ' . $this->userdata_table . ' WHERE uid = :uid';
        $sqlvalues[':uid'] = $work_uid;
        if($cond != null){
            foreach($cond as $k => $v){
                $key = ":" . $k;
                $sqlstring .= ' AND ' . $k . ' = ' . $key;
                $sqlvalues[$key] = $v;
            }
        }
        return $this->runSQL($sqlstring, $sqlvalues, "Get " . $this->userdata_table . " failed", 1);
    }
    // get udata (wrapper), return json object (array)
    public function get_udata($uid = null){
        $userinfo = $this->get_users($uid);
        if($this->isFailed()){
            return;
        }
        if(! isset($userinfo[0])){
            $this->errMessage = "no user data";
            $this->errCode = 1;
            return;
        }
        if((! isset($userinfo[0]["udata"])) || (strlen($userinfo[0]['udata']) == 0)){
            $udata = array();
        }else{
            $udata = json_decode($userinfo[0]["udata"], true); // note: $udata is an object array
            if($udata == null){
                /*
                $this->errMessage = "udata corrupted";
                $this->errCode = 1;
                return;
                */
                $udata = array();
            }
        }
        return $udata;
    }
    // check exist (return true or false)
    public function is_user_exist($email){
        $userinfo = $this->get_users_byemail($email);
        if($this->isFailed()){
            return false;
        }
        if(! isset($userinfo[0])){
            return false;
        }
        return;
    }
    public function get_last_users_id(){
        $sqlstring = "SELECT max(id) as lastID from users";
        $sqlvalues = array();
        $rarray = $this->runSQL($sqlstring, $sqlvalues, "LastID " . $this->users_table . " failed", 2);
        if($this->isFailed()){
            return 0;
        }
        if(! isset($rarray[0])){
            return 0;
        }
        if($rarray[0]["lastID"] == null){
            return 0;
        }
        return $rarray[0]["lastID"];
    }
    public function get_last_userdata_id($uid = null){
        // specify uid
        $work_uid = $this->valid_uid($uid);
        if($work_uid == null){
            return 0;
        }
        $sqlstring = 'SELECT max(wid) as lastID from userdata WHERE uid=:uid';
        $sqlvalues[':uid'] = $work_uid;
        //$sqlstring = "SELECT max(wid) from userdata WHERE uid=".$work_uid;
        $rarray = $this->runSQL($sqlstring, $sqlvalues, "LastID " . $this->userdata_table . " failed", 2);
        if($this->isFailed()){
            return 0;
        }
        if(! isset($rarray[0])){
            return 0;
        }
        if($rarray[0]["lastID"] == null){
            return 0;
        }
        return $rarray[0]["lastID"];
    }
    /*
     * Error handling
     */
    public function isFailed(){
        if($this->errCode != 0 || $this->errMessage != ""){
            return TRUE;
        }
        return FALSE;
    }
    public function getErrMessage(){
        return $this->errMessage;
    }
    public function getErrCode(){
        return $this->errCode;
    }
}
?>
